define(['app', 'json5', 'clipboard', 'jquery.format'], function(app, JSON5, Clipboard) {
    app.controller('ApiDocGeneratorController', function($http, $routeParams, xUtil, toastr) {
        var self = this;

        self.code = '';
        self.apiParams = [{
            name: 'api',
            checked: true,
            rows: [[{
                name: 'method', value: 'get', format: '{s}', type: 'select', width: 3,
                options: [{
                    value: 'get', label: 'GET'
                }, {
                    value: 'post', label: 'POST'
                }, {
                    value: 'put', label: 'PUT'
                }, {
                    value: 'delete', label: 'DELETE'
                }, {
                    value: 'head', label: 'HEAD'
                }, {
                    value: 'options', label: 'OPTIONS'
                }]
            }, {
                name: 'path', value: '', type: 'text', width: 6, placeholder: 'path'
            }, {
                name: 'title', value: '', type: 'text', width: 3, placeholder: '[title]'
            }]]
        }, {
            name: 'apiDefine',
            checked: true,
            rows: [[{
                name: 'name', value: '', type: 'text', width: 3, placeholder: 'name'
            }, {
                name: 'title', value: '', type: 'text', width: 3, placeholder: '[title]'
            }, {
                name: 'description', value: '', type: 'text', width: 6, placeholder: '[description]'
            }]]
        }, {
            name: 'apiDeprecated',
            checked: true,
            rows: [[{
                name: 'text', value: '', type: 'text', width: 6, placeholder: '[text]'
            }]]
        }, {
            name: 'apiDescription',
            checked: true,
            rows: [[{
                name: 'text', value: '', type: 'text', width: 6, placeholder: 'text'
            }]]
        }, {
            name: 'apiError',
            checked: true,
            rows: [[{
                name: 'group', value: '', format: '(s)', type: 'text', width: 3, placeholder: '[(group)]'
            }, {
                name: 'type', value: '', format: '(s)', type: 'text', width: 3, placeholder: '[{type}]'
            }, {
                name: 'field', value: '', type: 'text', width: 3, placeholder: 'field'
            }, {
                name: 'description', value: '', type: 'text', width: 3, placeholder: '[description]'
            }]]
        }, {
            name: 'apiErrorExample',
            checked: true,
            rows: [[{
                name: 'type', value: '', format: '{s}', type: 'text', width: 3, placeholder: '[{type}]'
            }, {
                name: 'title', value: '', type: 'text', width: 3, placeholder: '[title]'
            }], [{
                name: 'example', value: '', type: 'textarea', width: 12, placeholder: 'example'
            }]]
        }, {
            name: 'apiExample',
            checked: true,
            rows: [[{
                name: 'type', value: '', format: '{s}', type: 'text', width: 3, placeholder: '[{type}]'
            }, {
                name: 'title', value: '', type: 'text', width: 3, placeholder: 'title'
            }], [{
                name: 'example', value: '', type: 'textarea', width: 12, placeholder: 'example'
            }]]
        }, {
            name: 'apiGroup',
            checked: true,
            rows: [[{
                name: 'name', value: '', type: 'text', width: 3, placeholder: 'name'
            }]]
        }, {
            name: 'apiHeader',
            checked: true,
            rows: [[{
                name: 'group', value: '', format: '(s)', type: 'text', width: 3, placeholder: '[(group)]'
            }, {
                name: 'type', value: '', format: '{s}', type: 'text', width: 3, placeholder: '[{type}]'
            }, {
                name: 'field', value: '', format: '[s]', type: 'text', width: 3, placeholder: '[field]', optional: false
            }, {
                name: 'description', value: '', type: 'text', width: 3, placeholder: '[description]'
            }]]
        }, {
            name: 'apiHeaderExample',
            checked: true,
            rows: [[{
                name: 'type', value: '', format: '{s}', type: 'text', width: 3, placeholder: '[{type}]'
            }, {
                name: 'title', value: '', type: 'text', width: 3, placeholder: '[title]'
            }], [{
                name: 'example', value: '', type: 'textarea', width: 12, placeholder: 'example'
            }]]
        }, {
            name: 'apiIgnore',
            checked: true,
            rows: [[{
                name: 'hint', value: '', type: 'text', width: 3, placeholder: '[hint]'
            }]]
        }, {
            name: 'apiName',
            checked: true,
            rows: [[{
                name: 'name', value: '', type: 'text', width: 3, placeholder: 'name'
            }]]
        }, {
            name: 'apiParam',
            checked: true,
            rows: [[{
                name: 'group', value: '', format: '(s)', type: 'text', width: 3, placeholder: '[(group)]'
            }, {
                name: 'type', value: '', format: '{s}', type: 'text', width: 3, placeholder: '[{type}]'
            }, {
                name: 'field', value: '', format: '[s]', type: 'text', width: 3, placeholder: '[field]', optional: false
            }, {
                name: 'description', value: '', type: 'text', width: 3, placeholder: '[description]'
            }]]
        }, {
            name: 'apiParamExample',
            checked: true,
            rows: [[{
                name: 'type', value: '', format: '{s}', type: 'text', width: 3, placeholder: '[{type}]'
            }, {
                name: 'title', value: '', type: 'text', width: 3, placeholder: '[title]'
            }], [{
                name: 'example', value: '', type: 'textarea', width: 12, placeholder: 'example'
            }]]
        }, {
            name: 'apiPermission',
            checked: true,
            rows: [[{
                name: 'name', value: '', type: 'text', width: 3, placeholder: 'name'
            }]]
        }, {
            name: 'apiPrivate',
            checked: true,
            rows: []
        }, {
            name: 'apiSampleRequest',
            checked: true,
            rows: [[{
                name: 'url', value: '', type: 'text', width: 6, placeholder: 'url'
            }]]
        }, {
            name: 'apiSuccess',
            checked: true,
            rows: [[{
                name: 'group', value: '', format: '(s)', type: 'text', width: 3, placeholder: '[(group)]'
            }, {
                name: 'type', value: '', format: '{s}', type: 'text', width: 3, placeholder: '[{type}]'
            }, {
                name: 'field', value: '', type: 'text', width: 3, placeholder: 'field'
            }, {
                name: 'description', value: '', type: 'text', width: 3, placeholder: '[description]'
            }]]
        }, {
            name: 'apiSuccessExample',
            checked: true,
            rows: [[{
                name: 'type', value: '', format: '{s}', type: 'text', width: 3, placeholder: '[{type}]'
            }, {
                name: 'title', value: '', type: 'text', width: 3, placeholder: '[title]'
            }], [{
                name: 'example', value: '', type: 'textarea', width: 12, placeholder: 'example'
            }]]
        }, {
            name: 'apiUse',
            checked: true,
            rows: [[{
                name: 'name', value: '', type: 'text', width: 3, placeholder: 'name'
            }]]
        }, {
            name: 'apiVersion',
            checked: true,
            rows: [[{
                name: 'version', value: '', type: 'text', width: 3, placeholder: 'version'
            }]]
        }];

        self.init = function() {
            new Clipboard('#copy').on('success', function(e) {
                toastr.success('已复制到剪贴板！');
            });

            var repeatNodes = [{
                name: 'apiHeader',
                times: 3
            }, {
                name: 'apiParam',
                times: 3
            }, {
                name: 'apiSuccess',
                times: 3
            }];
            _.forEach(self.apiParams, function(apiParam) {
                _.forEach(repeatNodes, function(node) {
                    if (apiParam.name == node.name) {
                        apiParam['multiple'] = true;
                        /*_.forEach(_.range(node.times - 1), function() {
                            apiParam.rows.push(angular.copy(apiParam.rows[0]));
                        });*/
                    }
                });
            });
            // load mock
            if ($routeParams.path) {
                loadMockApiDoc();
            }
        }

        function loadMockApiDoc() {
            $http({
                method: 'POST',
                url: '/' + $routeParams.path + '?origin=true',
                transformResponse: function(response) {
                    return response;
                }
            }).then(function(response) {
                var path = $routeParams.path,
                    extname = path.substring(path.lastIndexOf('.')),
                    filename = path.substring(path.lastIndexOf('/') + 1);

                var title = xUtil.regex.subMatch(response.data, /^@标题：(.*)/gm);

                var url = xUtil.regex.urlMatch(response.data, path);

                var method = xUtil.regex.subMatch(response.data, /^@Method：([A-Za-z]+)/gmi).toLowerCase();
                method = (method == '' ? 'get' : method);

                // api
                setApiParam('api', function(param) {
                    param.rows[0][0].value = method;
                    param.rows[0][1].value = url;
                    param.rows[0][2].value = title;
                });
                // apiPrivate
                setApiParam('apiPrivate', function(param) {
                    param.checked = false;
                });
                // apiSampleRequest
                setApiParam('apiSampleRequest', function(param) {
                    param.rows[0][0].value = 'off';
                });

                // apiParamExample
                try {
                    var requestBody = xUtil.regex.keyMatch(response.data, '入参');
                    setApiParam('apiParamExample', function(param) {
                        param.rows[0][0].value = extname.substring(1);
                        param.rows[0][1].value = '入参';
                        param.rows[1][0].value = getAndFormatBody(extname, requestBody);
                    });
                } catch (e) {
                    toastr.error('解析【入参】错误：' + e);
                }

                // apiHeaderExample
                try {
                    var headers = xUtil.regex.keyMatch(response.data, 'Headers');
                    setApiParam('apiHeaderExample', function(param) {
                        param.rows[0][0].value = 'json';
                        param.rows[0][1].value = 'Headers';
                        param.rows[1][0].value = getAndFormatBody('.json', headers);
                    });
                } catch (e) {
                    toastr.error('解析【Headers】错误：' + e);
                }

                // apiErrorExample
                var errors = xUtil.regex.keyMatch(response.data, '错误');
                if (!isEmpty(errors)) {
                    setApiParam('apiErrorExample', function(param) {
                        param.rows[0][0].value = 'text';
                        param.rows[0][1].value = '错误';
                        param.rows[1][0].value = errors;
                    });
                }

                // apiSuccessExample
                try {
                    var responseBody = response.data.trim();
                    setApiParam('apiSuccessExample', function(param) {
                        param.rows[0][0].value = extname.substring(1);
                        param.rows[0][1].value = '出参';
                        param.rows[1][0].value = getAndFormatBody(extname, responseBody);
                    });
                } catch (e) {
                    toastr.error('解析【出参】错误：' + e);
                }
            });
        }

        function getAndFormatBody(extname, content) {
            if (extname == '.json') {
                content = (isEmpty(content) ? '{}' : content);
                return JSON.stringify(JSON5.parse(content), null, 4);
            } else if (extname == '.xml') {
                content = (isEmpty(content) ? '<xml/>' : content);
                // remove comments and format
                return jQuery.format(jQuery.format(content, { method: 'xmlmin' }), { method: 'xml' }).trim();
            }
        }

        function setApiParam(name, handler) {
            var apiParam = _.find(self.apiParams, function(item) {
                return item.name == name;
            });
            if (apiParam) {
                handler(apiParam);
            }
        }

        function isEmpty(value) {
            return value.replace(/^s+|s+$/g, '') === '';
        }

        self.generate = function(valid) {
            self.code = '';
            if (valid) {
                var code = '/**';
                _.forEach(self.apiParams, function(apiParam) {
                    if (apiParam.checked) {
                        var params = '', values = '';
                        if (!apiParam['multiple']) {
                            params = '\n * @' + apiParam.name;
                        }

                        _.forEach(apiParam.rows, function(row) {
                            if (apiParam['multiple']) {
                                params = '\n * @' + apiParam.name;
                                values = '';
                            }
                            _.forEach(row, function(item) {
                                if (item.value) {
                                    var value = '';
                                    if (item.optional === true) {
                                        item.format = '[s]';
                                    } else if (item.optional === false) {
                                        item.format = 's';
                                    }
                                    if (item.format) {
                                        value = item.format.replace('s', item.value);
                                    } else {
                                        value = item.value;
                                    }
                                    if (item.name == 'example') {
                                        value = ('\n' + value).replace(/\n/g, '\n *   ');
                                    } else {
                                        value = ' ' + value;
                                    }
                                    values += value
                                }
                            });
                            if (apiParam['multiple'] && !isEmpty(values)) {
                                code += params + values;
                            }
                        });
                        if (!apiParam['multiple'] && !isEmpty(values)) {
                            code += params + values;
                        }
                        if (_.size(apiParam.rows) == 0) {
                            code += params;
                        }
                    }
                });
                code += '\n */';

                self.code = code;
            }
        }

        self.reset = function() {
            self.code = '';
            _.forEach(self.apiParams, function(apiParam) {
                apiParam.checked = true;
                _.forEach(apiParam.rows, function(row) {
                    _.forEach(row, function(item) {
                        if (item.type == 'select') {
                            item.value = item.options[0].value;
                        } else {
                            item.value = '';
                        }
                        if (item.optional !== undefined) {
                            item.optional = false;
                        }
                    });
                });
            });
        }
    });
});
